﻿// 837. 连通块中点的数量.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

using namespace std;
/*
https://www.acwing.com/problem/content/839/

给定一个包含 n 个点（编号为 1∼n）的无向图，初始时图中没有边。

现在要进行 m 个操作，操作共有三种：

C a b，在点 a 和点 b 之间连一条边，a 和 b 可能相等；
Q1 a b，询问点 a 和点 b 是否在同一个连通块中，a 和 b 可能相等；
Q2 a，询问点 a 所在连通块中点的数量；
输入格式
第一行输入整数 n 和 m。

接下来 m 行，每行包含一个操作指令，指令为 C a b，Q1 a b 或 Q2 a 中的一种。

输出格式
对于每个询问指令 Q1 a b，如果 a 和 b 在同一个连通块中，则输出 Yes，否则输出 No。

对于每个询问指令 Q2 a，输出一个整数表示点 a 所在连通块中点的数量

每个结果占一行。

数据范围
1≤n,m≤105
输入样例：
5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5
输出样例：
Yes
2
3
*/

const int N = 100010;
int f[N];
int cnt[N];

int find(int x) {
	if (x != f[x]) f[x] = find(f[x]);
	return f[x];
}

void merge(int a, int b) {
	a = find(a); b = find(b);
	if (a != b) {
		f[a] = b;
		cnt[b] += cnt[a];
	}
}


void init() {
	for (int i = 0; i < N; i++) {
		f[i] = i;
		cnt[i] = 1;
	}
}

int n, m;

int main()
{
	init();

	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		string op; int a; int b;
		cin >> op;
		
		if (op == "C") {
			cin >> a >> b;
			a = find(a); b = find(b);
			if (a != b) {
				merge(a, b);
			}
		}
		else if (op == "Q1") {
			cin >> a >> b;
			a = find(a); b = find(b);
			if (a == b) {
				cout << "Yes" << endl;
			}
			else {
				cout << "No" << endl;
			}
		}
		else {
			cin >> a; a = find(a);
			cout << cnt[a] << endl;
		}
	}

	return 0;
}
